home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / haeberli / libgutil / subpix.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  8KB  |  374 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  *    subpix -
  19.  *        subpixel positioned trapazoid and line prims.
  20.  *
  21.  *    exports:
  22.             trappixel_callback(func)
  23.         trapspan_callback(func)
  24.         filltri(x0,y0,x1,y1,x2,y2,fatness)
  25.         filltrap(x0,y0,w0,x1,y1,w1,fatness)
  26.         subpixline(x0,y0,x1,y1,width)
  27.         void subpixpoint(fx,fy)
  28.  *
  29.  *    In general the floating point coordinate 0.0,0.0 maps to
  30.  *    the center of pixel [0,0].  Here are some examples of 
  31.  *    this sampling:
  32.  *
  33.  *    filltrap(-0.5,-0.5,1.0,-0.5,0.5,1.0,0.0) fills pixel[0,0]
  34.  *    subpixpoint(0.5,0.5) fills pixels [0,0], [0,1], [1,0], [1,1]
  35.  *    subpixline(-0.5,0.0,0.5,0.0,1.0) fills pixel [0,0]
  36.  *    
  37.  *                Paul Haeberli - 1990
  38.  *
  39.  */
  40. #include "math.h"
  41.  
  42. #define EPSILON    0.000001
  43.  
  44. float flerp();
  45.  
  46. static Xsubpixline();
  47. static Ysubpixline();
  48. static vline();
  49.  
  50. static void (*pixfunc)();
  51. static void (*spanfunc)();
  52.  
  53. static void defspanfunc(xmin, xmax, y)
  54. int xmin, xmax, y;
  55. {
  56.     int x;
  57.  
  58.     for(x=xmin; x<=xmax; x++)
  59.         (*pixfunc)(x,y);
  60. }
  61.  
  62. static void pixtospan(int x,int y)
  63. {
  64.     (*spanfunc)(x,x,y);
  65. }
  66.  
  67. trappixel_callback(func)
  68. void (*func)();
  69. {
  70.     pixfunc = func;
  71.     spanfunc = defspanfunc;
  72. }
  73.  
  74. trapspan_callback(func)
  75. void (*func)();
  76. {
  77.     spanfunc = func;
  78.     pixfunc = pixtospan;
  79. }
  80.  
  81. /*
  82.  *    filltri -
  83.  *        point sampling triangle fill. 
  84.  *
  85.  */
  86. filltri(x0,y0,x1,y1,x2,y2,fatness)
  87. float x0, y0, x1, y1, x2, y2, fatness;
  88. {
  89.     int i;
  90.     float pos[3][2], temp0, temp1, xmid, ymid, d, p, w;
  91.  
  92.     if(fatness>EPSILON) {
  93.     subpixline(x0,y0,x1,y1,fatness);
  94.     subpixline(x1,y1,x2,y2,fatness);
  95.     subpixline(x2,y2,x0,y0,fatness);
  96.     }
  97.     pos[0][0] = x0;
  98.     pos[0][1] = y0;
  99.     pos[1][0] = x1;
  100.     pos[1][1] = y1;
  101.     pos[2][0] = x2;
  102.     pos[2][1] = y2;
  103.     if(pos[1][1]<pos[0][1]) {
  104.     temp0 = pos[0][0];
  105.     temp1 = pos[0][1];
  106.     pos[0][0] = pos[1][0];
  107.     pos[0][1] = pos[1][1];
  108.     pos[1][0] = temp0;
  109.     pos[1][1] = temp1;
  110.     }
  111.     if(pos[2][1]<pos[1][1]) {
  112.     temp0 = pos[1][0];
  113.     temp1 = pos[1][1];
  114.     pos[1][0] = pos[2][0];
  115.     pos[1][1] = pos[2][1];
  116.     pos[2][0] = temp0;
  117.     pos[2][1] = temp1;
  118.     }
  119.     if(pos[1][1]<pos[0][1]) {
  120.     temp0 = pos[0][0];
  121.     temp1 = pos[0][1];
  122.     pos[0][0] = pos[1][0];
  123.     pos[0][1] = pos[1][1];
  124.     pos[1][0] = temp0;
  125.     pos[1][1] = temp1;
  126.     }
  127.     d = pos[2][1]-pos[0][1];
  128.     if(d<EPSILON)
  129.     p = 0.0;
  130.     else
  131.     p = (pos[1][1]-pos[0][1])/d;
  132.     xmid = flerp(pos[0][0],pos[2][0],p);
  133.     ymid = pos[1][1];
  134.     if(xmid<pos[1][0]) {
  135.     w = pos[1][0]-xmid;
  136.     filltrap(pos[0][0],pos[0][1],0.0,xmid,ymid,w,0.0);
  137.     filltrap(xmid,ymid,w,pos[2][0],pos[2][1],0.0,0.0);
  138.     } else {
  139.     w = xmid - pos[1][0];
  140.     filltrap(pos[0][0],pos[0][1],0.0,pos[1][0],pos[1][1],w,0.0);
  141.     filltrap(pos[1][0],pos[1][1],w,pos[2][0],pos[2][1],0.0,0.0);
  142.     }
  143. }
  144.  
  145. /*
  146.  *    filltrap -
  147.  *        point sampling trapazoid fill. Remember: y0 is assumed to 
  148.  *    be less than y1.
  149.  *
  150.  */
  151. filltrap(x0,y0,w0,x1,y1,w1,fatness)
  152. float x0, y0, w0, x1, y1, w1, fatness;
  153. {
  154.     float ymin, deltay, p, mp;
  155.     float rx0, rx1, xmin, xmax, yline;
  156.     int y, iyline, ixmin, ixmax;
  157.  
  158. /* surround it with lines if thick */
  159.     if(fatness>EPSILON) {
  160.     subpixline(x0,y0,x0+w0,y0,fatness);
  161.     subpixline(x0+w0,y0,x1+w1,y1,fatness);
  162.     subpixline(x1+w1,y1,x1,y1,fatness);
  163.     subpixline(x1,y1,x0,y0,fatness);
  164.     }
  165.  
  166.     x0 += 0.5;
  167.     y0 += 0.5;
  168.     x1 += 0.5;
  169.     y1 += 0.5;
  170.  
  171. /* find the height of the trap */
  172.     deltay = y1-y0;
  173.     if(deltay<EPSILON)
  174.     return 0;
  175.  
  176. /* get the right hand x coords */
  177.     rx0 = x0+w0-0.5;
  178.     rx1 = x1+w1-0.5;
  179.     x0 = x0+0.5;
  180.     x1 = x1+0.5;
  181.  
  182. /* get the first y scanline pos */
  183.     ymin = floor(y0)+0.5;
  184.  
  185. /* if below bottom, increment */
  186.     if(ymin<y0)
  187.     y = 1;
  188.     else
  189.     y = 0;
  190.     yline = ymin+y;
  191.     iyline = floor(yline);
  192.     while(yline<y1) {
  193.     p = (yline-y0)/deltay;    /* calculate parameter */
  194.     mp = 1.0-p;
  195.     xmin = mp*x0+p*x1;
  196.     xmax = mp*rx0+p*rx1;
  197.     ixmin = floor(xmin);
  198.     ixmax = floor(xmax);
  199.     if(ixmax>=ixmin)
  200.         (*spanfunc)(ixmin,ixmax,iyline);
  201.     y++;
  202.     iyline++;
  203.     yline = ymin+y;
  204.     }
  205. }
  206.  
  207. /*
  208.  *    subpixel positioned line
  209.  *
  210.  */
  211. subpixline(x0,y0,x1,y1,width)
  212. float x0, y0, x1, y1, width;
  213. {
  214.     float dx, dy;
  215.  
  216.     x0 += 0.5;
  217.     y0 += 0.5;
  218.     x1 += 0.5;
  219.     y1 += 0.5;
  220.  
  221.     dx = x1-x0;
  222.     if(dx<0.0)
  223.     dx = -dx;
  224.     dy = y1-y0;
  225.     if(dy<0.0)
  226.     dy = -dy;
  227.     if(dy>dx)
  228.     Ysubpixline(x0,y0,x1,y1,width);
  229.     else
  230.     Xsubpixline(x0,y0,x1,y1,width);
  231. }
  232.  
  233. static Xsubpixline(x0,y0,x1,y1,width)
  234. float x0, y0, x1, y1, width;
  235. {
  236.     float xmin, deltax, deltay, p, mp;
  237.     float ymin, xline;
  238.     int x, ixline, iymin;
  239.     float temp;
  240.     float w0, ry0, ry1, ymax;
  241.     int iymax;
  242.  
  243. /* swap endpoints if they're in the wrong order */
  244.     if(x1<x0) {
  245.     temp = x1;
  246.     x1 = x0;
  247.     x0 = temp;
  248.     temp = y1;
  249.     y1 = y0;
  250.     y0 = temp;
  251.     }
  252.  
  253. /* find the width of the line */
  254.     deltax = x1-x0;
  255.     deltay = y1-y0;
  256.     if(deltax<EPSILON)
  257.     return 0;
  258.  
  259. /* apply the width */
  260. #ifdef WIDTH_CORRECT
  261.     width = width*sqrt(deltax*deltax+deltay*deltay)/deltax;
  262. #endif
  263.     width = (width-1.0)/2.0;
  264.     ry0 = y0+width;
  265.     ry1 = y1+width;
  266.     y0 -= width;
  267.     y1 -= width;
  268.  
  269. /* get the first y scanline pos */
  270.     xmin = floor(x0)+0.5;
  271.  
  272. /* if to left of left , increment */
  273.     if(xmin<x0)
  274.     x = 1;
  275.     else
  276.     x = 0;
  277.     xline = xmin+x;
  278.     ixline = floor(xline);
  279.     while(xline<x1) {
  280.     p = (xline-x0)/deltax;    /* calculate parameter */
  281.     mp = 1.0-p;
  282.     ymin = mp*y0+p*y1;
  283.     ymax = mp*ry0+p*ry1;
  284.     iymin = floor(ymin);
  285.     iymax = floor(ymax);
  286.     if(iymax>=iymin)
  287.         vline(iymin,iymax,ixline);
  288.     x++;
  289.     ixline++;
  290.     xline = xmin+x;
  291.     }
  292. }
  293.  
  294. static Ysubpixline(x0,y0,x1,y1,width)
  295. float x0, y0, x1, y1, width;
  296. {
  297.     float ymin, deltax, deltay, p, mp;
  298.     float xmin, yline;
  299.     int y, iyline, ixmin;
  300.     float temp;
  301.     float w0, rx0, rx1, xmax;
  302.     int ixmax;
  303.  
  304. /* swap endpoints if they're in the wrong order */
  305.     if(y1<y0) {
  306.     temp = y1;
  307.     y1 = y0;
  308.     y0 = temp;
  309.     temp = x1;
  310.     x1 = x0;
  311.     x0 = temp;
  312.     }
  313.  
  314. /* find the height of the line */
  315.     deltax = x1-x0;
  316.     deltay = y1-y0;
  317.     if(deltay<EPSILON)
  318.     return 0;
  319.  
  320. /* apply the width */
  321. #ifdef WIDTH_CORRECT
  322.     width = width*sqrt(deltax*deltax+deltay*deltay)/deltay;
  323. #endif
  324.     width = (width-1.0)/2.0;
  325.     rx0 = x0+width;
  326.     rx1 = x1+width;
  327.     x0 -= width;
  328.     x1 -= width;
  329.  
  330. /* get the first y scanline pos */
  331.     ymin = floor(y0)+0.5;
  332.  
  333. /* if below bottom, increment */
  334.     if(ymin<y0)
  335.     y = 1;
  336.     else
  337.     y = 0;
  338.     yline = ymin+y;
  339.     iyline = floor(yline);
  340.     while(yline<y1) {
  341.     p = (yline-y0)/deltay;    /* calculate parameter */
  342.     mp = 1.0-p;
  343.     xmin = mp*x0+p*x1;
  344.     xmax = mp*rx0+p*rx1;
  345.     ixmin = floor(xmin);
  346.     ixmax = floor(xmax);
  347.     if(ixmax>=ixmin)
  348.         (*spanfunc)(ixmin,ixmax,iyline);
  349.     y++;
  350.     iyline++;
  351.     yline = ymin+y;
  352.     }
  353. }
  354.  
  355. void subpixpoint(fx,fy)
  356. float fx, fy;
  357. {
  358.     int ix, iy;
  359.  
  360.     ix = (int) floor(fx);
  361.     iy = (int) floor(fy);
  362.     (*spanfunc)(ix,ix+1,iy);
  363.     (*spanfunc)(ix,ix+1,iy+1);
  364. }
  365.  
  366. static vline(ymin,ymax,x)
  367. int ymin, ymax, x;
  368. {
  369.     int y;
  370.  
  371.     for(y=ymin; y<=ymax; y++)
  372.     (*pixfunc)(x,y);
  373. }
  374.